import os
from datetime import datetime, timedelta
from calendar import monthrange
from decimal import Decimal
from flask import (
    render_template,
    request,
    flash,
    redirect,
    url_for,
    jsonify,
    g,
    send_from_directory,
    Blueprint,
)
from models import (
    app,
    User,
    Jobnumber,
    Category,
    Subcategory,
    Task,
    Assignment,
    db,
    Holiday,
    Attachment,
)
from sqlalchemy.sql import func, extract
from flask_login import (
    LoginManager,
    login_required,
    login_user,
    logout_user,
    current_user,
)
from flask_wtf import FlaskForm
from functools import wraps
import plotly
import plotly.graph_objs as go
import json
import pandas as pd
import numpy as np
from itertools import groupby
from operator import itemgetter
from models import db
from collections import namedtuple
from base64 import b64encode, b64decode
from werkzeug.utils import secure_filename
from uuid import uuid4
import unicodedata
from werkzeug.urls import url_quote


bp_partner = Blueprint("bp_partner", __name__)

BASE_DIR = os.path.dirname(__file__)
# UPLOAD_DIR = os.path.join(BASE_DIR,'task','upload')
# 为了使 测试机和 正式机附件同步 把上传文件放在外面
UPLOAD_DIR = "/home/fanwenjie/jmo-calendar-upload"

# 用于返回用户未来 n 月负荷
def get_user_loads_month(load_range, now):
    n = load_range if load_range <= 12 else 12
    # now = datetime.now()
    this_year = now.year
    this_month = now.month
    months = {}
    # format
    # {
    #    month : [start_date, days, work_hour]
    # }

    for i in range(n):
        month = this_month + i
        year = this_year
        if month > 12:
            month -= 12
            year = this_year + 1
        days_count = monthrange(year, month)[1]
        month_start_date = now.replace(year=year, month=month, day=1).date()
        months[month] = [month_start_date, days_count, 0]

    start_date = now.replace(day=1).date()
    last_month_start_date, last_month_days, _ = months[list(months.keys())[-1]]
    end_date = last_month_start_date + timedelta(days=last_month_days - 1)

    # days 字典 储存 周,是否工作日
    days = {}
    # format
    # {
    #    date : [month, is_workday]
    # }
    for month, (month_start_date, days_count, _) in months.items():
        for i in range(days_count):
            date = month_start_date + timedelta(days=i)
            day_index = date.isocalendar()[2]
            if day_index in [6, 7]:
                isworkday = False
            else:
                isworkday = True
            days[date] = [month, isworkday]

    # 根据假期表修正days 字典 假日与补班
    holidays = (
        db.session.query(Holiday.date, Holiday.isworkday)
        .filter_by(delete=False)
        .filter(Holiday.date >= start_date)
        .filter(Holiday.date <= end_date)
        .all()
    )

    for date, isworkday in holidays:
        days[date][1] = isworkday

    # 根据是否工作日 计算每周理论工时总数
    for _, (month, isworkday) in days.items():
        if isworkday:
            months[month][2] += 8

    # 获取任务列表
    assignments = (
        db.session.query(
            Assignment.receiverid,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
        )
        .filter_by(delete=False)
        .filter(Assignment.enddate >= start_date)
        .filter(Assignment.startdate <= end_date)
        .all()
    )

    # 计算每个人每月 被分配的工时总和
    assignment_summary_month = {}
    for assignment in assignments:
        receiverid, start, end, rate = assignment
        if not assignment_summary_month.get(receiverid):
            assignment_summary_month[receiverid] = dict(
                (month, 0) for month in months.keys()
            )

        # 超出计算部分不算
        if start < start_date:
            start = start_date
        if end > end_date:
            end = end_date

        # 计算每天、每周工时总和
        for i in range((end - start).days + 1):
            day = start + timedelta(days=i)
            month = days[day][0]
            if days[day][1]:
                assignment_summary_month[receiverid][month] += 8 * rate

    # 折算百分比
    for user, data in assignment_summary_month.items():
        for month, hour in data.items():
            total = months[month][2]
            assignment_summary_month[user][month] = int(hour / total * 100)

    return (months.keys(), assignment_summary_month)


# 用于返回用户未来 n 周负荷
def get_user_loads_week(load_range, now):
    n = load_range if load_range <= 52 else 52
    # now = datetime.now()
    this_year = now.year
    this_week_number = now.isocalendar()[1]

    weeks = {}
    # format
    # {
    #    week_number : [start, end, work_hour]
    # }

    # 用于测试 12.31 的数据
    # this_week_number = 52
    # this_week_number = 5

    # 使用格式获取每周第一天 datetime.strptime("2019-W15-1", "%Y-W%W-%w")
    start_date = datetime.strptime(
        "{0}-W{1}-{2}".format(this_year, this_week_number - 1, 1), "%Y-W%W-%w"
    ).date()
    end_date = start_date + timedelta(days=7 * n - 1)

    for i in range(n):
        week = this_week_number + i
        week_start_date = start_date + timedelta(days=7 * i)
        week_end_date = start_date + timedelta(days=7 * i + 6)
        end_week_number = week_end_date.isocalendar()[1]
        week = week if week == end_week_number else end_week_number
        weeks[week] = [week_start_date, week_end_date, 0]

    # days 字典 储存 周,是否工作日
    days = {}
    # format
    # {
    #    date : [week_number, is_workday]
    # }
    for week_number, (week_start_date, _, _) in weeks.items():
        for i in range(7):
            # 默认 1~5 工作日 6,7 休息
            isworkday = True if i < 5 else False
            date = week_start_date + timedelta(days=i)
            days[date] = [week_number, isworkday]

    # 根据假期表修正days 字典 假日与补班
    holidays = (
        db.session.query(Holiday.date, Holiday.isworkday)
        .filter_by(delete=False)
        .filter(Holiday.date >= start_date)
        .filter(Holiday.date <= end_date)
        .all()
    )
    for date, isworkday in holidays:
        days[date][1] = isworkday

    # 根据是否工作日 计算每周理论工时总数
    for _, (week_number, isworkday) in days.items():
        if isworkday:
            weeks[week_number][2] += 8

    # 获取任务列表
    assignments = (
        db.session.query(
            Assignment.receiverid,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
        )
        .filter_by(delete=False)
        .filter(Assignment.enddate >= start_date)
        .filter(Assignment.startdate <= end_date)
        .all()
    )

    # 计算每个人每天、每周 被分配的工时总和
    assignment_summary_week = {}
    for assignment in assignments:
        receiverid, start, end, rate = assignment
        if not assignment_summary_week.get(receiverid):
            assignment_summary_week[receiverid] = dict(
                (week, 0) for week in weeks.keys()
            )

        # 超出计算部分不算
        if start < start_date:
            start = start_date
        if end > end_date:
            end = end_date

        # 计算每天、每周工时总和
        for i in range((end - start).days + 1):
            day = start + timedelta(days=i)
            week = days[day][0]

            if days[day][1]:
                assignment_summary_week[receiverid][week] += 8 * rate

    # 折算百分比
    for u, d in assignment_summary_week.items():
        for w, h in d.items():
            total = weeks[w][2]
            assignment_summary_week[u][w] = int(h / total * 100)

    return (weeks.keys(), assignment_summary_week)


# 用于返回用户未来 n 天负荷
def get_user_loads_day(load_range, now):
    n = load_range
    # now = datetime.now()
    start_date = now.date()
    end_date = start_date + timedelta(days=n - 1)

    # days 字典 储存 是否工作日
    days = {}
    # format
    # {
    #    date : is_workday
    # }
    for i in range(n):
        date = start_date + timedelta(days=i)
        day_index = date.isocalendar()[2]
        if day_index in [6, 7]:
            days[date] = False
        else:
            days[date] = True

    # 根据假期表修正days 字典 假日与补班
    holidays = (
        db.session.query(Holiday.date, Holiday.isworkday)
        .filter_by(delete=False)
        .filter(Holiday.date >= start_date)
        .filter(Holiday.date <= end_date)
        .all()
    )
    for date, isworkday in holidays:
        days[date] = isworkday

    # 获取任务列表
    assignments = (
        db.session.query(
            Assignment.receiverid,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
        )
        .filter_by(delete=False)
        .filter(Assignment.enddate >= start_date)
        .filter(Assignment.startdate <= end_date)
        .all()
    )

    # 计算每个人每天、每周 被分配的工时总和
    assignment_summary_day = {}
    for assignment in assignments:
        receiverid, start, end, rate = assignment
        if not assignment_summary_day.get(receiverid):
            assignment_summary_day[receiverid] = dict((day, 0) for day in days.keys())

        # 超出计算部分不算
        if start < start_date:
            start = start_date
        if end > end_date:
            end = end_date

        # 计算每天、每周工时总和
        for i in range((end - start).days + 1):
            day = start + timedelta(days=i)
            if days[day]:
                assignment_summary_day[receiverid][day] += 8 * rate

    # 折算百分比
    for u, data in assignment_summary_day.items():
        for d, h in data.items():
            assignment_summary_day[u][d] = int(h / 8 * 100)

    return ([day.strftime("%d") for day in days.keys()], assignment_summary_day)


# task routes....
@bp_partner.route("/tasks/<user_id>", methods=["GET"])
@login_required
def tasks(user_id):
    tasks = (
        db.session.query(
            Task.id,
            Task.title,
            Task.remark,
            Task.userid,
            Task.categoryid,
            Task.subcategoryid,
            Task.jobnumberid,
            Task.manhour,
            Task.tasktime,
            Task.createtime,
            Task.edittime,
            Task.delete,
            User.name,
            Category.name,
            Subcategory.name,
            Jobnumber.name,
        )
        .filter_by(userid=user_id)
        .filter_by(delete=False)
        .join(Jobnumber, Jobnumber.id == Task.jobnumberid)
        .join(User, User.id == Task.userid)
        .join(Category, Category.id == Task.categoryid)
        .join(Subcategory, Subcategory.id == Task.subcategoryid)
        .all()
    )
    try:
        user_name = db.session.query(User.name).filter(User.id == user_id).all()[0][0]
    except:
        user_name = "不存在"
    flash("支持模糊搜索:空格 *。如 搜索2月份包含AD的事件: 2019-02-* AD ", category="info")
    flash("也支持正则搜索 如 搜索非休假事件 ^((?!休假).)*$ ", category="success")
    return render_template(
        "partner/tasks.html", tasks=tasks, user_name=user_name, user_id=user_id
    )


@bp_partner.route("/list", methods=["GET"])
@login_required
def list_users():
    load_type = request.args.get("type")
    load_range = request.args.get("range")
    load_back_days = request.args.get("back")
    if load_type not in ["day", "week", "month"]:
        load_type = "week"
    else:
        flash("需要不同的负荷周期可在地址栏调整Range数值", category="info")
    try:
        load_range = int(load_range)
    except:
        load_range = 3
    if load_range > 100 or load_range < 1:
        load_range = 10

    try:
        load_back_days = int(load_back_days)
    except:
        load_back_days = 0
    if load_back_days < 0:
        load_back_days = 0

    now = datetime.now() - timedelta(days=load_back_days)

    if load_type == "week":
        fields, user_loads = get_user_loads_week(load_range, now)
    if load_type == "day":
        fields, user_loads = get_user_loads_day(load_range, now)
    if load_type == "month":
        fields, user_loads = get_user_loads_month(load_range, now)

    users = (
        db.session.query(User.id, User.no, User.name, User.position)
        .filter_by(delete=False)
        .filter(User.id != 1)
        .filter(User.id != 4)
        .filter(User.id != 116)
        .filter(User.id != 117)
        .filter(User.id != 118)
        .all()
    )
    return render_template(
        "partner/users.html",
        users=users,
        fields=fields,
        user_loads=user_loads,
        load_type=load_type,
    )


@bp_partner.route("/<user_id>/assignments/receive")
@login_required
def receive(user_id):
    receiver_name = db.session.query(User.name).filter(User.id == user_id).all()[0][0]
    assignments = (
        db.session.query(
            Assignment.id,
            Assignment.title,
            Assignment.remark,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
            Assignment.createtime,
            User.no,
            User.name,
            Jobnumber.name,
            Jobnumber.desc,
            Assignment.finish,
            Assignment.grade,
            Assignment.edittime,
            User.id.label("sender_id"),
        )
        .filter(Assignment.receiverid == user_id)
        .filter(Assignment.delete == False)
        .join(User, User.id == Assignment.senderid)
        .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
        .all()
    )
    holidaysArray = (
        db.session.query(Holiday.date, Holiday.desc, Holiday.isworkday)
        .filter_by(delete=False)
        .all()
    )
    holidaysOffset = {}
    holidays = {}
    for holiday in holidaysArray:
        d = holiday[0].strftime("%Y-%m-%d")
        if holiday[2]:
            holidaysOffset[d] = holiday[1]
        else:
            holidays[d] = holiday[1]
    return render_template(
        "partner/assignments.html",
        assignments=assignments,
        receiver_name=receiver_name,
        receiver_id=int(user_id),
        holidays=json.dumps(holidays),
        holidaysOffset=json.dumps(holidaysOffset),
    )


@bp_partner.route("/<user_id>/assignments/send")
@login_required
def send(user_id):
    sender_name = db.session.query(User.name).filter(User.id == user_id).all()[0][0]
    assignments = (
        db.session.query(
            Assignment.id,
            Assignment.title,
            Assignment.remark,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
            Assignment.createtime,
            User.no,
            User.name,
            Jobnumber.name,
            Jobnumber.desc,
            Assignment.finish,
            Assignment.grade,
            Assignment.edittime,
            User.id.label("receiver_id"),
        )
        .filter(Assignment.senderid == user_id)
        .filter(Assignment.delete == False)
        .join(User, User.id == Assignment.receiverid)
        .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
        .all()
    )
    holidaysArray = (
        db.session.query(Holiday.date, Holiday.desc, Holiday.isworkday)
        .filter_by(delete=False)
        .all()
    )
    holidaysOffset = {}
    holidays = {}
    for holiday in holidaysArray:
        d = holiday[0].strftime("%Y-%m-%d")
        if holiday[2]:
            holidaysOffset[d] = holiday[1]
        else:
            holidays[d] = holiday[1]
    return render_template(
        "partner/assignments.html",
        assignments=assignments,
        sender_name=sender_name,
        sender_id=int(user_id),
        holidays=json.dumps(holidays),
        holidaysOffset=json.dumps(holidaysOffset),
    )


@bp_partner.route("/assignment/<assignment_id>/edit")
@login_required
def edit(assignment_id):
    assignment = (
        db.session.query(Assignment.senderid.label("sender_id"), Assignment.delete)
        .filter_by(id=assignment_id)
        .all()
    )
    if not assignment:
        flash("任务不存在。", category="danger")
        return redirect(url_for("bp_partner.send", user_id=current_user.id), code=302)
    if assignment[0].delete:
        flash("任务已删除。", category="danger")
        return redirect(url_for("bp_partner.send", user_id=current_user.id), code=302)
    if assignment[0].sender_id != current_user.id:
        flash("你无权操作。", category="danger")
        return redirect(url_for("bp_partner.send", user_id=current_user.id), code=302)

    senderid = current_user.id
    sender_name = db.session.query(User.name).filter(User.id == senderid).all()[0][0]
    jobnumbers = (
        db.session.query(Jobnumber.id, Jobnumber.name, Jobnumber.desc)
        .filter_by(delete=False)
        .all()
    )
    assignment = (
        db.session.query(
            Assignment.id,
            Assignment.title,
            Assignment.remark,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
            User.id,
            User.name,
            Jobnumber.id,
            Jobnumber.name,
            Jobnumber.desc,
        )
        .filter(Assignment.id == assignment_id)
        .join(User, User.id == Assignment.receiverid)
        .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
        .all()[0]
    )
    return render_template(
        "partner/assign.html",
        users=((senderid, sender_name), (assignment[6], assignment[7])),
        jobnumbers=jobnumbers,
        assignment=assignment,
    )


@bp_partner.route("/assignment/<assignment_id>/view")
@login_required
def view(assignment_id):
    senderid = current_user.id
    sender_name = db.session.query(User.name).filter(User.id == senderid).all()[0][0]
    jobnumbers = (
        db.session.query(Jobnumber.id, Jobnumber.name, Jobnumber.desc)
        .filter_by(delete=False)
        .all()
    )
    assignment = (
        db.session.query(
            Assignment.id,
            Assignment.title,
            Assignment.remark,
            Assignment.startdate,
            Assignment.enddate,
            Assignment.taskrate,
            User.id,
            User.name,
            Jobnumber.id,
            Jobnumber.name,
            Jobnumber.desc,
        )
        .filter(Assignment.id == assignment_id)
        .join(User, User.id == Assignment.receiverid)
        .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
        .all()[0]
    )
    attachments = (
        db.session.query(
            Attachment.id,
            Attachment.file_name,
            Attachment.display_name,
            Attachment.create_time,
            Attachment.edit_time,
            Attachment.delete,
        )
        .filter_by(assignment_id=assignment_id)
        .all()
    )
    return render_template(
        "partner/assign.html",
        users=((senderid, sender_name), (assignment[6], assignment[7])),
        jobnumbers=jobnumbers,
        assignment=assignment,
        view=True,
        attachments=attachments,
    )


@bp_partner.route("/uploads/<path:file_name>/<int:attachment_id>")
@login_required
def download(file_name, attachment_id):
    attachment = (
        db.session.query(Attachment.display_name).filter_by(id=attachment_id).first()
    )
    display_name = attachment.display_name
    d = send_from_directory(directory=UPLOAD_DIR, filename=file_name)
    try:
        filename = display_name.encode("latin-1")
    except UnicodeEncodeError:
        filenames = {
            "filename": unicodedata.normalize("NFKD", display_name).encode(
                "latin-1", "ignore"
            ),
            "filename*": "UTF-8''{}".format(url_quote(display_name)),
        }
    else:
        filenames = {"filename": filename}

    d.headers.set("Content-Disposition", "attachment", **filenames)
    return d


@bp_partner.route("/assignment/<int:assignment_id>/attachment", methods=["GET", "POST"])
@login_required
def attachment(assignment_id):
    if request.method == "GET":
        assignment_id = assignment_id
        assignment = (
            db.session.query(Assignment.senderid.label("sender_id"), Assignment.delete)
            .filter_by(id=assignment_id)
            .all()
        )
        attachments = (
            db.session.query(
                Attachment.id,
                Attachment.file_name,
                Attachment.display_name,
                Attachment.create_time,
                Attachment.edit_time,
                Attachment.delete,
            )
            .filter_by(assignment_id=assignment_id)
            .all()
        )
        if not assignment:
            flash("任务不存在。", category="danger")
            return redirect(
                url_for("bp_partner.send", user_id=current_user.id), code=302
            )
        if assignment[0].delete:
            flash("任务已删除。", category="danger")
            return redirect(
                url_for("bp_partner.send", user_id=current_user.id), code=302
            )
        if assignment[0].sender_id != current_user.id:
            flash("你无权操作。", category="danger")
            return redirect(
                url_for("bp_partner.send", user_id=current_user.id), code=302
            )

        flash("上传完成后刷新页面查看结果。", category="success")
        flash("下载完后请手工重命名。", category="warning")
        return render_template(
            "partner/attachment.html",
            assignment_id=assignment_id,
            attachments=attachments,
        )
    if request.method == "POST":
        f = request.files["files[]"]
        display_name = f.filename
        file_name = uuid4().hex
        fp = os.path.join(UPLOAD_DIR, file_name)

        # print(fp,f.filename)
        f.save(fp)

        attachment = Attachment(
            assignment_id=assignment_id,
            file_name=file_name,
            display_name=display_name,
            create_time=datetime.now(),
        )
        db.session.add(attachment)
        db.session.commit()

        return jsonify(
            {
                "status": "ok",
                "uploaddir": UPLOAD_DIR,
                "filename": file_name,
                "displayname": display_name,
            }
        )


@bp_partner.route("/assignment/<assignment_id>/grade", methods=["GET", "POST"])
@login_required
def grade(assignment_id):
    if request.method == "GET":
        senderid = current_user.id
        sender_name = (
            db.session.query(User.name).filter(User.id == senderid).all()[0][0]
        )
        assignment = (
            db.session.query(
                Assignment.id,
                Assignment.title,
                Assignment.remark,
                Assignment.startdate,
                Assignment.enddate,
                Assignment.taskrate,
                User.id,
                User.name,
                Jobnumber.id,
                Jobnumber.name,
                Jobnumber.desc,
            )
            .filter(Assignment.id == assignment_id)
            .join(User, User.id == Assignment.receiverid)
            .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
            .all()[0]
        )
        return render_template(
            "partner/grade.html",
            users=((senderid, sender_name), (assignment[6], assignment[7])),
            assignment=assignment,
        )
    if request.method == "POST":
        grade = request.form.get("grade")
        senderid = request.form.get("senderid").strip()
        if int(senderid) == current_user.id:
            try:
                grade = int(grade)
            except:
                grade = 0
            assignment = Assignment.query.filter_by(id=assignment_id).first()
            assignment.grade = grade
            assignment.edittime = datetime.now()
            db.session.commit()
            flash("打分成功。", category="success")
        else:
            flash("你无权打分。", category="danger")

        return redirect(url_for("bp_partner.send", user_id=current_user.id), code=302)


@bp_partner.route("/assignment/<assignment_id>/delete")
@login_required
def delete(assignment_id):
    senderid = (
        db.session.query(Assignment.senderid)
        .filter(Assignment.id == assignment_id)
        .all()[0][0]
    )
    if senderid == current_user.id:
        assignment = Assignment.query.filter_by(id=assignment_id).first()
        assignment.delete = True
        assignment.edittime = datetime.now()
        db.session.commit()
        flash("删除成功。", category="success")
    else:
        flash("你无权删除该任务", category="danger")
    return redirect(url_for("bp_partner.send", user_id=current_user.id), code=302)


@bp_partner.route("/attachment/<attachment_id>/delete")
@login_required
def attachment_delete(attachment_id):
    data = (
        db.session.query(
            Attachment.delete, Attachment.assignment_id, Assignment.senderid
        )
        .filter(Attachment.id == attachment_id)
        .join(Assignment, Assignment.id == Attachment.assignment_id)
        .all()
    )

    if not data:
        return "附件不存在!"
    else:
        senderid = data[0].senderid
        if senderid == current_user.id:
            attachment = Attachment.query.filter_by(id=attachment_id).first()
            attachment.delete = True
            attachment.edit_time = datetime.now()
            db.session.commit()
            flash("删除成功。", category="success")
        else:
            flash("你无权删除该附件", category="danger")
    return redirect(
        url_for("bp_partner.attachment", assignment_id=data[0].assignment_id), code=302
    )


@bp_partner.route("/assignment/<assignment_id>/finish")
@login_required
def finish(assignment_id):
    receiverid = (
        db.session.query(Assignment.receiverid)
        .filter(Assignment.id == assignment_id)
        .all()[0][0]
    )
    if receiverid == current_user.id:
        assignment = Assignment.query.filter_by(id=assignment_id).first()
        assignment.finish = True
        assignment.edittime = datetime.now()
        db.session.commit()
        flash("设置成功。", category="success")
    else:
        flash("你无权操作", category="danger")
    return redirect(url_for("bp_partner.receive", user_id=current_user.id), code=302)


@bp_partner.route("/assignment/<assignment_id>/unfinish")
@login_required
def unfinish(assignment_id):
    receiverid = (
        db.session.query(Assignment.receiverid)
        .filter(Assignment.id == assignment_id)
        .all()[0][0]
    )
    if receiverid == current_user.id:
        assignment = Assignment.query.filter_by(id=assignment_id).first()
        assignment.finish = False
        assignment.edittime = datetime.now()
        db.session.commit()
        flash("设置成功。", category="success")
    else:
        flash("你无权操作", category="danger")
    return redirect(url_for("bp_partner.receive", user_id=current_user.id), code=302)


@bp_partner.route("/assign/<user_id>/", methods=["GET", "POST"])
@login_required
def assign(user_id):
    if request.method == "GET":
        senderid = current_user.id
        receiverid = user_id
        sender_name = (
            db.session.query(User.name).filter(User.id == senderid).all()[0][0]
        )
        receiver_name = (
            db.session.query(User.name).filter(User.id == receiverid).all()[0][0]
        )
        jobnumbers = (
            db.session.query(Jobnumber.id, Jobnumber.name, Jobnumber.desc)
            .filter_by(delete=False)
            .all()
        )
        return render_template(
            "partner/assign.html",
            users=((senderid, sender_name), (receiverid, receiver_name)),
            jobnumbers=jobnumbers,
        )
    if request.method == "POST":
        submit_flag = True

        fields = {
            "title": "任务摘要",
            "remark": "任务明细",
            "receiverid": "任务接收者",
            "senderid": "任务发出者",
            "jobnumberid": "工作令号",
            "startdate": "开始日期",
            "enddate": "结束日期",
            "taskrate": "任务权重",
        }

        remark = request.form.get("remark").strip()
        receiverid = request.form.get("receiverid").strip()
        senderid = request.form.get("senderid").strip()

        title = request.form.get("title").strip()
        if title == "":
            submit_flag = False
            flash("任务摘要不能为空", category="danger")

        jobnumberid = request.form.get("jobnumberid").strip()
        if jobnumberid == "":
            submit_flag = False
            flash("工作令号不能为空", category="danger")

        startdate = request.form.get("startdate").strip()
        if startdate == "":
            submit_flag = False
            flash("开始日期不能为空", category="danger")
        else:
            startdate = datetime.strptime(startdate, "%m/%d/%Y")

        enddate = request.form.get("enddate").strip()
        if enddate == "":
            submit_flag = False
            flash("结束日期不能为空", category="danger")
        else:
            enddate = datetime.strptime(enddate, "%m/%d/%Y")

        if startdate > enddate:
            submit_flag = False
            flash("开始日期不能大于结束日期", category="danger")

        taskrate = request.form.get("taskrate").strip()
        if taskrate == "":
            submit_flag = False
            flash("任务权重不能为空", category="danger")

        if not submit_flag:
            return redirect(url_for("bp_partner.assign", user_id=user_id), code=302)

        assignmentid = request.form.get("assignmentid")
        if assignmentid:
            assignmentid = assignmentid.strip()
            assignment = Assignment.query.filter_by(id=assignmentid).first()
            assignment.title = title
            assignment.remark = remark
            assignment.jobnumberid = jobnumberid
            assignment.startdate = startdate
            assignment.enddate = enddate
            assignment.taskrate = taskrate
            assignment.edittime = datetime.now()
            db.session.commit()
            flash("任务修改成功。", category="success")
        else:
            assignment = Assignment(
                title=title,
                remark=remark,
                jobnumberid=jobnumberid,
                receiverid=receiverid,
                senderid=senderid,
                startdate=startdate,
                enddate=enddate,
                taskrate=taskrate,
                createtime=datetime.now(),
            )
            db.session.add(assignment)
            db.session.commit()
            flash("任务创建成功。", category="success")
        return redirect(url_for("bp_partner.send", user_id=current_user.id), code=302)


@bp_partner.route("/calendar/<user_id>/")
@login_required
def calendar(user_id):
    try:
        user_name = db.session.query(User.name).filter(User.id == user_id).all()[0][0]
    except:
        user_name = "不存在"
    holidaysArray = (
        db.session.query(Holiday.date, Holiday.desc, Holiday.isworkday)
        .filter_by(delete=False)
        .all()
    )
    holidaysOffset = {}
    holidays = {}
    for holiday in holidaysArray:
        d = holiday[0].strftime("%Y-%m-%d")
        if holiday[2]:
            holidaysOffset[d] = holiday[1]
        else:
            holidays[d] = holiday[1]
    return render_template(
        "partner/calendar.html",
        user_id=user_id,
        user_name=user_name,
        holidays=json.dumps(holidays),
        holidaysOffset=json.dumps(holidaysOffset),
    )


@bp_partner.route("/calendar/<user_id>/ajaxs/count")
@login_required
def get_user_day_count(user_id):
    userid = user_id
    start = request.args.get("start")
    end = request.args.get("end")
    tasks = (
        db.session.query(Task.tasktime, func.sum(Task.manhour).label("total"))
        .filter(Task.userid == userid)
        .filter(Task.delete == False)
        .filter(Task.tasktime < end)
        .filter(Task.tasktime >= start)
        .filter(Task.categoryid != 33)
        .group_by(Task.tasktime)
        .all()
    )
    vacations = (
        db.session.query(
            Task.subcategoryid, Subcategory.name, func.sum(Task.manhour).label("total")
        )
        .join(Subcategory, Subcategory.id == Task.subcategoryid)
        .filter(Task.userid == userid)
        .filter(Task.delete == False)
        .filter(Task.tasktime < end)
        .filter(Task.tasktime >= start)
        .filter(Task.categoryid == 33)
        .group_by(Task.subcategoryid)
        .all()
    )
    data = {}
    for task in tasks:
        d = task.tasktime.strftime("%Y-%m-%d")
        h = "%.1f" % task.total
        data[d] = h

    vacation = {}
    for v in vacations:
        _, a, b = v
        vacation[a] = b
    return jsonify({"task": data, "vacation": vacation})


@bp_partner.route("/calendar/<user_id>/ajaxs/events")
@login_required
def get_user_events(user_id):
    userid = user_id
    start = request.args.get("start")
    end = request.args.get("end")
    tasks = (
        db.session.query(
            Task.id,
            Task.title,
            Task.remark,
            Task.userid,
            Task.categoryid,
            Task.subcategoryid,
            Task.jobnumberid,
            Task.manhour,
            Task.tasktime,
            Task.createtime,
            Task.edittime,
            Task.delete,
            User.name,
            Category.name.label("category"),
            Category.color,
            Subcategory.name.label("subcategory"),
            Subcategory.color,
            Jobnumber.name.label("jobnumber"),
            Jobnumber.desc.label("project"),
        )
        .filter_by(userid=userid)
        .filter_by(delete=False)
        .filter(Task.tasktime <= end)
        .filter(Task.tasktime >= start)
        .join(Jobnumber, Jobnumber.id == Task.jobnumberid)
        .join(User, User.id == Task.userid)
        .join(Category, Category.id == Task.categoryid)
        .join(Subcategory, Subcategory.id == Task.subcategoryid)
        .all()
    )
    data = []
    for task in tasks:
        data.append(
            {
                "id": task.id,
                "title": task.title,
                "jobnumberid": task.jobnumberid,
                "jobnumber": task.jobnumber,
                "project": task.project,
                "remark": task.remark,
                "manhour": task.manhour,
                "categoryid": task.categoryid,
                "category": task.category,
                "subcategoryid": task.subcategoryid,
                "subcategory": task.subcategory,
                "start": task.tasktime.strftime("%Y-%m-%d"),
                "color": "#{}".format(task[14]),
            }
        )
    return jsonify(data)


@bp_partner.route("/<user_id>/assignments/ajax")
@login_required
def get_user_assignments(user_id):
    userid = user_id
    start = request.args.get("start")
    end = request.args.get("end")
    user = request.args.get("user")
    if user == "receiver":
        assignments = (
            db.session.query(
                Assignment.id,
                Assignment.title,
                Assignment.remark,
                Assignment.startdate,
                Assignment.enddate,
                Assignment.taskrate,
                Assignment.finish,
                Jobnumber.name,
                User.name,
            )
            .filter(Assignment.receiverid == userid)
            .filter_by(delete=False)
            .filter(Assignment.enddate >= start)
            .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
            .join(User, User.id == Assignment.senderid)
            .all()
        )
    else:
        assignments = (
            db.session.query(
                Assignment.id,
                Assignment.title,
                Assignment.remark,
                Assignment.startdate,
                Assignment.enddate,
                Assignment.taskrate,
                Assignment.finish,
                Jobnumber.name,
                User.name,
            )
            .filter(Assignment.senderid == userid)
            .filter_by(delete=False)
            .filter(Assignment.enddate >= start)
            .join(Jobnumber, Jobnumber.id == Assignment.jobnumberid)
            .join(User, User.id == Assignment.receiverid)
            .all()
        )

    data = []
    colors = [
        "#00BFFF",
        "#00FFFF",
        "#1E90FF",
        "#40E0D0",
        "#48D1CC",
        "#6495ED",
        "#66CDAA",
        "#7FFFD4",
        "#87CEEB",
        "#87CEFA",
        "#ADD8E6",
        "#AFEEEE",
        "#B0C4DE",
        "#B0E0E6",
        "#BDB76B",
        "#D8BFD8",
        "#DA70D6",
        "#DDA0DD",
        "#DEB887",
        "#E0FFFF",
        "#E6E6FA",
        "#E9967A",
        "#EE82EE",
        "#EEE8AA",
        "#F08080",
        "#F0E68C",
        "#F0F8FF",
        "#F0FFF0",
        "#F0FFFF",
        "#F5DEB3",
        "#F5F5DC",
        "#F5F5F5",
        "#F5FFFA",
        "#F8F8FF",
        "#FA8072",
        "#FAEBD7",
        "#FAF0E6",
        "#FAFAD2",
        "#FDF5E6",
        "#FFA07A",
        "#FFDAB9",
        "#FFDEAD",
        "#FFE4B5",
        "#FFE4C4",
        "#FFE4E1",
        "#FFEBCD",
        "#FFEFD5",
        "#FFF0F5",
        "#FFF5EE",
        "#FFF8DC",
        "#FFFACD",
        "#FFFAF0",
        "#FFFAFA",
        "#FFFF00",
        "#FFFFE0",
        "#FFFFF0",
    ]
    i = 0
    for task in assignments:
        if user == "receiver":
            txt = "发起人:" + task[-1]
        else:
            txt = "接受人:" + task[-1]
        if task.finish:
            color = "#9EFFBD"
        else:
            color = colors[i]
            i += 1
            if i > colors.__len__() - 1:
                i = 0

        data.append(
            {
                "id": task.id,
                "title": txt
                + " 权重:"
                + str(int(task.taskrate * 100))
                + "% "
                + task[-2]
                + ":"
                + task.title,
                "remark": task.remark,
                "manhour": 0,
                "start": task.startdate.strftime("%Y-%m-%d") + " 00:00:00",
                "end": task.enddate.strftime("%Y-%m-%d") + " 23:59:59",
                "color": color,
            }
        )

    return jsonify(data)


if __name__ == "__main__":
    pass
